/*
 *   Licensed to the Apache Software Foundation (ASF) under one
 *   or more contributor license agreements.  See the NOTICE file
 *   distributed with this work for additional information
 *   regarding copyright ownership.  The ASF licenses this file
 *   to you under the Apache License, Version 2.0 (the
 *   "License"); you may not use this file except in compliance
 *   with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing,
 *   software distributed under the License is distributed on an
 *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *   KIND, either express or implied.  See the License for the
 *   specific language governing permissions and limitations
 *   under the License.
 *
 */

package org.apache.directory.server.codec.json.operations.search;


import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.List;

import org.apache.directory.shared.ldap.filter.SearchScope;
import org.apache.directory.shared.ldap.message.AliasDerefMode;
import org.apache.directory.shared.ldap.message.SearchRequestImpl;
import org.apache.directory.shared.ldap.name.DN;

import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;


/**
 * TODO SearchRequestDecoder.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class SearchRequestCodec implements JsonDeserializer<SearchRequestImpl>, JsonSerializer<SearchRequestImpl>
{

    private static final String BASE_DN = "baseDn";
    private static final String FILTER = "filter";
    private static final String SCOPE = "scope";
    private static final String TYPES_ONLY = "typesOnly";
    private static final String SIZE_LIMIT = "sizeLimit";
    private static final String TIME_LIMIT = "timeLimit";
    private static final String ALIAS_DEREF_MODE = "aliasDerefMode";
    private static final String ATTRIBUTES = "attributes";


    public SearchRequestImpl deserialize( JsonElement json, Type typeOfT, JsonDeserializationContext context )
        throws JsonParseException
    {
        SearchRequestImpl req = null;

        try
        {
            JsonObject obj = json.getAsJsonObject();

            req = new SearchRequestImpl();

            req.setBase( new DN( obj.get( BASE_DN ).getAsString() ) );
            req.setFilter( obj.get( FILTER ).getAsString() );

            JsonElement scopeEl = obj.get( SCOPE );
            if ( scopeEl != null )
            {
                int scope = SearchScope.getSearchScope( scopeEl.getAsString() );
                req.setScope( SearchScope.getSearchScope( scope ) );
            }

            JsonElement typesOnlyEl = obj.get( TYPES_ONLY );
            if ( typesOnlyEl != null )
            {
                req.setTypesOnly( typesOnlyEl.getAsBoolean() );
            }

            JsonElement sizeLimitEl = obj.get( SIZE_LIMIT );
            if ( sizeLimitEl != null )
            {
                req.setSizeLimit( sizeLimitEl.getAsInt() );
            }

            JsonElement timeLimitEl = obj.get( TIME_LIMIT );
            if ( timeLimitEl != null )
            {
                req.setTimeLimit( timeLimitEl.getAsInt() );
            }

            JsonElement aliasDerefModeEl = obj.get( ALIAS_DEREF_MODE );
            if ( aliasDerefModeEl != null )
            {
                req.setDerefAliases( AliasDerefMode.getDerefMode( aliasDerefModeEl.getAsInt() ) );
            }

            JsonElement attributesEl = obj.get( ATTRIBUTES );
            if ( attributesEl != null )
            {
                JsonArray ja = attributesEl.getAsJsonArray();
                Iterator<JsonElement> itr = ja.iterator();
                while( itr.hasNext() )
                {
                    req.addAttributes( itr.next().getAsString() );
                }
            }
        }
        catch ( Exception e )
        {
            e.printStackTrace();
        }

        return req;
    }


    public JsonElement serialize( SearchRequestImpl req, Type typeOfSrc, JsonSerializationContext context )
    {
        JsonObject json = new JsonObject();
        json.addProperty( BASE_DN, req.getBase().getName() );
        json.addProperty( FILTER, req.getFilter().toString() );
        
        if( req.getScope() != null )
        {
            json.addProperty( SCOPE, req.getScope().getLdapUrlValue() );
        }
        
        json.addProperty( TYPES_ONLY, req.getTypesOnly() );
        json.addProperty( SIZE_LIMIT, req.getSizeLimit() );
        json.addProperty( TIME_LIMIT, req.getTimeLimit() );
        json.addProperty( ALIAS_DEREF_MODE, req.getDerefAliases().getValue() );
        
        List<String> attributes = req.getAttributes();
        if( !attributes.isEmpty() )
        {
            JsonArray ja = new JsonArray();
            for( String s : attributes )
            {
                ja.add( new JsonPrimitive( s ) );
            }
            
            json.add( ATTRIBUTES, ja );
        }
        
        return json;
    }

}
